BABYLON.Effect.ShadersStore[`customPBRVertexShader`] = /* glsl */ `
    // precision mediump float;
    precision highp float;
    attribute vec3 position;
    attribute vec3 normal;
    attribute vec2 uv;
    attribute vec4 tangent; // xyz: tangent方向, w: handedness（+1 or -1）
    uniform mat4 worldView;
    uniform mat4 world;
    uniform mat4 projection;
    varying vec3 vNormal;
    varying vec3 vViewPos;
    varying vec2 vUV;
    varying mat3 vTBN;
    void main() {
        // vNormal = normalMatrix * normal;
        // vec3 newnormal = vec3(normal.xy,normal.z*-1.0);
         // 计算 TBN 矩阵（转为眼空间）
        vec3 N = normalize(mat3(worldView) * normal);
        vec3 T = normalize(mat3(worldView) * tangent.xyz);
        vec3 B = normalize(cross(N, T)) * tangent.w;
        vTBN = mat3(T, B, N);  // 切线空间 → 眼空间
        vNormal = N;
        vUV = uv;
        vViewPos = (worldView * vec4(position, 1.0)).xyz;
        gl_Position = projection *  vec4(vViewPos, 1.0);
    }
`;

BABYLON.Effect.ShadersStore[`customPBRFragmentShader`] = /* glsl */ `
    // precision mediump float;
    precision highp float;
    varying vec3 vViewPos;
    varying vec3 vNormal;
    uniform vec3 uLightWorldPos;
    uniform float uLightDensity;
    uniform float uAmbientDensity;
    uniform sampler2D albedoTexture;
    uniform sampler2D roughnessTexture;
    uniform sampler2D metallicRoughnessTexture;
    uniform sampler2D normalTexture;
    uniform mat4 view;
    varying vec2 vUV;
    varying mat3 vTBN;
    const float PI = 3.141592653589793;
    // 计算法线分布 D项
    float GGX(vec3 N,vec3 H,float roughness){
      float alpha = roughness * roughness;
      float t = dot(N,H)*dot(N,H)*(alpha*alpha-1.0)+1.0;
      float theta = alpha*alpha/(PI*t*t);
      return theta;
    }
    // 计算几何遮蔽 G项
    float SchlickGGX(vec3 N,vec3 V,vec3 L,float roughness){
      float k = (roughness + 1.0) * (roughness + 1.0) / 8.0;
      float NdotV = max(dot(N,V),0.0);
      float NdotL = max(dot(N,L),0.0);
      float Gv = NdotV/(NdotV*(1.0-k)+k);
      float Gl = NdotL/(NdotL*(1.0-k)+k);
      return Gv*Gl;
    }
     // 计算几何遮蔽 G项(更精确)
    float SmithGGX(vec3 N,vec3 V,vec3 L,float roughness){
      float a = roughness * roughness;
      float NdotV = max(dot(N,V),0.0);
      float NdotL = max(dot(N,L),0.0);
      float Gv = 2.0*NdotV/(NdotV+sqrt(a*a+(1.0-a*a)*NdotV*NdotV));
      float Gl = 2.0*NdotL/(NdotL+sqrt(a*a+(1.0-a*a)*NdotL*NdotL));
      return Gv*Gl;
    }
    // 计算菲涅尔 F项
    float SchlickFresnel(vec3 H,vec3 V,float F0){
      float VoH = max(dot(V,H),0.0);
      float f = F0 + (1.0 - F0) * pow(1.0 - VoH, 5.0);   // 菲涅尔
      return f;
    }
    // Lambert漫反射
    vec3 lambert(vec3 color,float F,float kd){
      return (1.0 - F) /PI* color * kd;
    }
    void main() {
        // 从法线贴图采样切线空间法线，范围 [0,1] → [-1,+1]
      vec4 albedo = texture2D(albedoTexture, vUV);
      vec3 tangentNormal = normalize(texture2D(normalTexture, vUV).rgb * 2.0 - 1.0);
      // tangentNormal.g = 1.0 - tangentNormal.g; // 修复法线贴图翻转(DiractX 风格的法线贴图使用)
      // 转换为视角空间
      vec3 viewNormal = normalize(vTBN * tangentNormal);
      float metallic = texture2D(metallicRoughnessTexture, vUV).b;  // 金属度
      float roughness = texture2D(metallicRoughnessTexture, vUV).g;   // 粗糙度
      vec3 N = normalize(viewNormal);
      vec3 LightViewPos = mat3(view) * uLightWorldPos;
      vec3 color = vec3(0.0);
      vec3 lightColor = vec3(0.6) * uLightDensity;
      vec3 ambientColor = vec3(1.0) * uAmbientDensity;  // 低亮度蓝灰色环境光
      vec3 lightDir = normalize(LightViewPos);
      vec3 viewDir = normalize(-vViewPos);
      vec3 halfway = normalize(viewDir + lightDir);
      // PBR
      float D = GGX(N,halfway,roughness);
      float G = SmithGGX(N,viewDir,lightDir,roughness);
      float F = SchlickFresnel(halfway,viewDir,metallic);   // 菲涅尔
      float NdotV = max(dot(N,viewDir),0.0);
      float NdotL = max(dot(N,lightDir),0.0);
      float specular = D*G*F/(4.0*NdotV*NdotL);
      // 防止除零，但背面光照应由其他逻辑剔除
      if (NdotL == 0.0 || NdotV == 0.0) {
          specular = 0.0;   // 跳过高光计算
      }
      vec3 skyColor = vec3(0.5, 0.7, 1.0);
      vec3 groundColor = vec3(0.05);
      vec3 ambient = mix(groundColor, skyColor, NdotL);

      vec3 diffuse = lambert(albedo.rgb,F,1.0);
      color = lightColor * specular + diffuse + ambient * albedo.rgb;  // 高光+漫反射+环境光
      gl_FragColor = vec4(color, 1.0);
    }
`;
// 自定义着色器
const PBRShader = (scene, index = 0) => {
  const shaderMaterial = new BABYLON.ShaderMaterial(
    "PBRShader" + index,
    scene,
    {
      vertex: `customPBR`,
      fragment: `customPBR`,
    },
    {
      attributes: ["position", "normal", "uv", "tangent"],
      uniforms: [
        "worldView",
        "view",
        "world",
        "projection",
        "uLightWorldPos",
        "uLightDensity",
      ],
      samplers: ["albedoTexture", "roughnessTexture", "metallicTexture"],
    }
  );
  // 传递 自定义uniform
  shaderMaterial.setVector3("uLightWorldPos", new BABYLON.Vector3(0, 100, 100));
  shaderMaterial.setFloat("uLightDensity", 0.15);
  shaderMaterial.setFloat("uAmbientDensity", 1.0);

  return shaderMaterial;
};

export { PBRShader };
